Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add moduleMetdata decorator for supplying common Angular metadata #2959

Merged
merged 17 commits into from
Feb 19, 2018
Merged

Add moduleMetdata decorator for supplying common Angular metadata #2959

merged 17 commits into from
Feb 19, 2018

Conversation

jonrimmer
Copy link
Contributor

Issue: #2694

What I did

This PR adds a decorator called moduleMetadata() to @storybook/angular that can be used to supply common metadata to all the Angular stories registered by a call to storiesOf().

How to test

The new decorator has an associated test that is ran as part of the core:

yarn test --core

The angular-cli example has been updated to demonstrate use of the new decorator.

The Angular guide has been updated to describe the use of the existing moduleMetadata parameter on stories, and the use of the new decorator.

@codecov
Copy link

codecov bot commented Feb 12, 2018

Codecov Report

Merging #2959 into master will increase coverage by 0.04%.
The diff coverage is n/a.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #2959      +/-   ##
==========================================
+ Coverage   37.28%   37.32%   +0.04%     
==========================================
  Files         435      435              
  Lines        9432     9427       -5     
  Branches      926      896      -30     
==========================================
+ Hits         3517     3519       +2     
+ Misses       5336     5335       -1     
+ Partials      579      573       -6
Impacted Files Coverage Δ
app/angular/src/client/index.js 0% <ø> (ø) ⬆️
app/vue/src/server/utils.js 0% <0%> (-100%) ⬇️
app/react/src/server/config/babel.js 0% <0%> (-100%) ⬇️
app/react/src/server/babel_config.js 0% <0%> (-76.67%) ⬇️
app/react-native/src/preview/story_kind.js 0% <0%> (ø) ⬆️
lib/ui/src/modules/api/index.js 0% <0%> (ø) ⬆️
addons/knobs/src/components/types/Array.js 34.14% <0%> (ø) ⬆️
...s/actions/src/lib/types/function/createFunction.js 53.33% <0%> (ø) ⬆️
...react-native/src/manager/components/PreviewHelp.js 0% <0%> (ø) ⬆️
app/angular/src/server/ts_config.js 38.09% <0%> (ø) ⬆️
... and 67 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 4f545e8...4f135ec. Read the comment docs.

@jonrimmer
Copy link
Contributor Author

I'm not really sure why those CI tests are failing?

@igor-dv
Copy link
Member

igor-dv commented Feb 13, 2018

I'll check your PR today =) Thanks !

@@ -1,4 +1,4 @@
import { storiesOf } from '@storybook/angular';
import { storiesOf, moduleMetadata } from '@storybook/angular';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think better having a separate example of this usage, also because it's necessary to check it in conjunction with addon-knobs.
How will it work with template instead of component prop?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added. Seems to work fine with template. I don't see any reason why they should affect each other, as this only touches the metadata, and passes other parts of the story through untouched.

})(() => ({
component: MockComponent,
moduleMetadata: {
providers: MockService,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should it be an array?

@@ -0,0 +1,42 @@
import { moduleMetadata } from './decorators';
Copy link
Member

@igor-dv igor-dv Feb 13, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we also need to support an arrays concatenation...

for example:

const result = moduleMetadata({
  imports: [FooModule],
})(() => ({
  component: MockComponent,
  moduleMetadata: {
    imports: [BarModule],
  }
}));

I would expect to have both FooModule and BarModule

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have modified it to combine rather than override.

@igor-dv
Copy link
Member

igor-dv commented Feb 13, 2018

Also, I see "netlify" is failing. DId you manage to run yarn bootstrap without any issues?

@jonrimmer
Copy link
Contributor Author

@igor-dv Yeah, I can run bootstrap without any problems. Not really sure what netlify is, or how I could have broken it? It was the CI CLI step that was failing earlier.

Copy link
Member

@igor-dv igor-dv left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.
@alterx, do you wanna add your two cents?

export const moduleMetadata = (metadata: Partial<NgModuleMetadata>) => (storyFn: () => any) => {
const story = storyFn();
const storyMetadata = story.moduleMetadata || {};
metadata = metadata || {};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can the default be introduced in the method signature?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's how I did it originally, but default params affect undefined or no value, but not null. So I'd need to add a check for null and assignment to {} anyway.

@@ -64,3 +64,40 @@ storiesOf('Custom ngModule metadata', module)
},
};
});

storiesOf('Common ngModule metadata', module)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you please extract it to a separate file? So it will play nicely with #2885 and #2918

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, it'd be better to have a separate example that shows:

  1. An example with this decorator (basic usage)
  2. Decorator + Knobs addon
  3. Decorator + Knobs + template
  4. Decorator + knobs + component

We don't have official docs for most of this and we usually point people to the examples so we try to keep as many as we can with all the use cases

Copy link
Contributor Author

@jonrimmer jonrimmer Feb 17, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess I'm not really seeing what value these examples would have? All this decorator does is allow you to declare a set of metadata that is shared amongst your subsequent stories. Whether you're using knobs, template, component, etc. is completely orthogonal to it. Since there is already examples of those things, I'm not sure how duplicating them here would really help understanding it?

Wouldn't it make more sense to modify all the other examples to use this decorator where appropriate, i.e. instead of supplying duplicate metadata, as in custom-pipes and custom-providers? Then the metadata example file could just be:

  1. An example with metadata supplied on the story.
  2. Metadata supplied using this decorator.
  3. Metadata supplied on the story that combines with that from the decorator.

@alterx
Copy link
Member

alterx commented Feb 15, 2018

I added a small comment regarding the examples, other than that it looks good to me.

Also, let's make sure that this works if we add it as a 'global' decorator (https://storybook.js.org/addons/introduction/#storybook-decorators) instead of using it inside a story (it should work but let's test it, just in case)

# Conflicts:
#
examples/angular-cli/src/stories/__snapshots__/custom-providers.stories.
storyshot
#	examples/angular-cli/src/stories/custom-metadata.stories.ts
@jonrimmer
Copy link
Contributor Author

@alterx I've added the test, though it feels a little wrong to be testing something that's purely provided by the core module here.

Copy link
Member

@igor-dv igor-dv left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happened to the stories? Or you didn't finish yet?

@@ -29,4 +30,5 @@ declare module '@storybook/angular' {
export function addDecorator(decorator: any): IApi;
export function configure(loaders: () => NodeRequire, module: NodeModule): void;
export function getStorybook(): IStoribookSection[];
export function clearDecorators(): void;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding this here makes it a public API. I think we don't want to expose this method.

@jonrimmer
Copy link
Contributor Author

@igor-dv I've removed clearDecorators from the top level export, although it's still importable from @storybook/angular/client (and always was, if you cast the * export of that module to any). As I understand it, this just how the JS module system works, as there's no concept of "package private" exports.

WRT the stories, I added a reply about this elsewhere but it seems to have gone missing. I'm not sure it makes sense to just have a single example file using this decorator, containing examples with component, template, knobs, etc. The use of this decorator is entirely orthogonal to those use-cases, and I'm not sure they would aid users in understanding it. I think it would be better to use this decorator in all the examples, where it makes sense. E.g. in custom-pipes.stories.ts so you don't have to declare the same metadata twice.

The specific metadata example(s) could then be focussed on demonstrating scenarios relating to metadata only. I.e.

  1. Adding metadata data on individual stories.
  2. Adding common metadata to be shared between several stories.
  3. Adding common metadata, and metadata on an individual story that is combined with it.

I'll update the PR to reflect this approach.

@igor-dv
Copy link
Member

igor-dv commented Feb 19, 2018

As I understand it, this just how the JS module system works, as there's no concept of "package private" exports.

Yeah, but if it's not on a top level, IMO we can breaking change easier =)

WRT the stories

Makes sense to me

Copy link
Member

@igor-dv igor-dv left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🍺

@Hypnosphi
Copy link
Member

Hypnosphi commented Feb 19, 2018

Please update integration test screenshot for angular:

cd examples/angular-cli
yarn build-storybook
cd ../..
yarn test --integration --update

@Hypnosphi Hypnosphi merged commit 6335274 into storybookjs:master Feb 19, 2018
@jonrimmer
Copy link
Contributor Author

🎉 🍻 Thanks for all your help guys!

@jonrimmer jonrimmer deleted the angular-modulemetadata-decorator branch February 19, 2018 23:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants